﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace LC01_Reflect
{
    class Program
    {
        static void Main(string[] args)
        {
            //普通反射
            Reflex1();

            //内部反射
            Reflex2();

            //通过反射调用方法
            Reflex3();

            //通过反射获取和设置字段和属性
            Reflex4();

            //反射新能测试
            Show();

            Console.Read();
        }

        private static void Reflex4()
        {
            Assembly assembly = Assembly.Load("LC01_Reflect");
            Type type = assembly.GetType("LC01_Reflect.Person");
            object oInstance = Activator.CreateInstance(type);
            PropertyInfo propertyInfo = type.GetProperty("Name");
            propertyInfo.SetValue(oInstance, "sssss");
            object resName = propertyInfo.GetValue(oInstance);

            FieldInfo filedinfo = type.GetField("age");
            filedinfo.SetValue(oInstance, 5);
            object resAge = filedinfo.GetValue(oInstance);
        }

        private static void Reflex3()
        {
            Assembly assembly = Assembly.Load("LC01_Reflect");
            Type type = assembly.GetType("LC01_Reflect.Person");
            object oInstance = Activator.CreateInstance(type);
            MethodInfo method = type.GetMethod("Say");
            // 无参数方法调用
            //method.Invoke(oInstance, new object[] { });
            //method.Invoke(oInstance, new object[0]);
            //method.Invoke(oInstance, null);
            // 有参数方法调用
            method.Invoke(oInstance, new object[] {"222" });
            // 私有方法调用
            MethodInfo method2 = type.GetMethod("PSay", BindingFlags.NonPublic | BindingFlags.Instance);
            method2.Invoke(oInstance, new object[] { "String" });
            // 静态方法
            MethodInfo method3 = type.GetMethod("SSay", BindingFlags.Public | BindingFlags.Static);//搜索指定名字的公共静态方法
            method3.Invoke(null, new object[] { "333" });//调用接收返回值
            // 有参数 且为ref 方法调用
            string str = "1";
            object[] invokeParas = new object[] { str };   //参数对象数组
            bool ret2 = (bool)type.GetMethod("SayRef").Invoke(oInstance, invokeParas);                        //Invoke执行    
            string msg2 = invokeParas[0].ToString();
            // 静态方法2-不用创建实例，直接调用实例中的方法，用于获取单例
            // 获取静态方法
            MethodInfo methodInfo = type.GetMethod("Instance", BindingFlags.Public | BindingFlags.Static);
            if (methodInfo != null)
            {
                // 调用静态方法
                Person person = methodInfo.Invoke(null, null) as Person;
            }
            else
            {
                Console.WriteLine("静态方法未找到");
            }
        }

        private static void Reflex2()
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            object obj = assembly.CreateInstance("LC01_Reflect.Person");
            //或者
            Type type = Type.GetType("LC01_Reflect.Person");
            obj = Activator.CreateInstance(type);
            Person s = obj as Person;
        }

        private static void Reflex1()
        {
            //第一种方法：直接加载dll
            //Assembly assembly = Assembly.LoadFrom("LC01_Reflect.dll");
            //第二种方法：提供路径的加载dll
            //Assembly assembly = Assembly.LoadFile(@"X://xxx.dll");
            //第三种方法：经常用到，被反射的dll存在被替换的情况。本文中的所有情况，都会占用dll资源，导致无法覆盖dll
            //byte[] filedata = File.ReadAllBytes("ATL.AutoTestReport.TestItems.dll");
            //Assembly assembly = Assembly.Load(filedata);
            Assembly assembly = Assembly.Load("LC01_Reflect");

            Type type1 = assembly.GetType("LC01_Reflect.Person");
            object c = Activator.CreateInstance(type1);
            Person s = c as Person;
        }


        public static void Show()
        {
            Console.WriteLine("*******************测试性能*******************");
            long commonTime = 0;
            long reflectionTime = 0;
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();
                for (int i = 0; i < 1000_000; i++)
                {
                    Person person = new Person();
                    //person.Say("Test");
                }
                watch.Stop();
                commonTime = watch.ElapsedMilliseconds;
            }
            {
                Stopwatch watch = new Stopwatch();
                Assembly assembly = Assembly.Load("LC01_Reflect");//1 动态加载
                Type type1 = assembly.GetType("LC01_Reflect.Person");//2 获取类型
                watch.Start();  
                for (int i = 0; i < 1000_000; i++)
                {
                    object person = Activator.CreateInstance(type1);//3 创建对象                    
                }
                watch.Stop();
                reflectionTime = watch.ElapsedMilliseconds;
            }
            Console.WriteLine($"正常new实例化时间：{commonTime}ms, 反射时间：{reflectionTime}ms");
        }
    }

}
